/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ia_psr.graph;

/**
 *
 * @author Rubén Avalos Elvira y Fabiana Celiberti Tapie
 */
import ia_psr.problemas.transportes.Conductor;
import ia_psr.problemas.IProblema;
import ia_psr.problemas.Variable;
import java.util.ArrayList;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

public class GrafoEmpresaTransportes extends GrafoRestricciones {
    protected PropertyChangeSupport changeSupport;

    public GrafoEmpresaTransportes() {
        super(null);
        changeSupport = new PropertyChangeSupport(this);        
    }

    public GrafoEmpresaTransportes(IProblema p) {
        super(p);
        changeSupport = new PropertyChangeSupport(this);
    }

    public GrafoEmpresaTransportes(IProblema p, ArrayList<Tarea> tareas) {
        super(p);

        changeSupport = new PropertyChangeSupport(this);

        for (Tarea t : tareas) {
            nodos.add(t);
        }

        crearRestricciones();
    }

    public void crearRestricciones() {

        eliminarRestricciones();

        for (Nodo n1 : nodos) {
            Tarea t1 = (Tarea)n1;
            for (Nodo n2 : nodos) {
                Tarea t2 = (Tarea)n2;
                if (    t1.programada()  && t2.programada() &&
                        !t1.equals(t2)   &&
                        t1.seSolapan(t2) && !adjacents(t1, t2)  ) {
                    System.out.println("Se solapa " + t1.nombre + " con " + t2.nombre);
                    addRestriccion(t1, t2);
                }
            }
        }
    }

    protected void eliminarRestricciones() {
        for (Nodo n : nodos) {
            n.aristas.clear();
        }
    }

    public void asignVariable(NodoPSR n, Variable v) {
        n.valor = v;
        if (n instanceof Tarea && v instanceof Conductor) {
            Tarea t = (Tarea)n;
            Conductor c = (Conductor)v;
            c.asignarTarea(t);
        }
    }

    public void deasignVariable(NodoPSR n, Variable v) {
        //n.valor.value = null;
        n.valor.setValue(null);
        if (n instanceof Tarea && v instanceof Conductor) {
            Tarea t = (Tarea)n;
            Conductor c = (Conductor)v;
            c.deasignarTarea(t);
        }
    }

    @Override
    // Deasigna los posibles conductores que tuviera asignados la tarea. Ademas,
    // ponemos las tareas no programadas al final de la lista.
    public void resetAllNodos() {
        super.resetAllNodos();
        while (tareasNoProgramadasDesordenadas()) {
            for (int i = 0, j = 1; j < nodos.size(); ++i, ++j) {
                Tarea ti = (Tarea)nodos.get(i);
                Tarea tj = (Tarea)nodos.get(j);
                // Si la siguiente tarea a una tarea no programada es programada,
                // querra decir que esta por en medio de la lista todavia
                if (!ti.programada() && tj.programada()) {
                    nodos.remove(i);
                    nodos.add(nodos.size(), ti);
                    System.out.println("Tarea " + ti.nombre + " cambiada de sitio.");
                    --i;
                    --j;
                }
            }
        }
        crearRestricciones();
    }

    protected boolean tareasNoProgramadasDesordenadas() {
        for (int i = 0, j = 1; j < nodos.size(); ++i, ++j) {
            Tarea ti = (Tarea)nodos.get(i);
            Tarea tj = (Tarea)nodos.get(j);
            // Si la siguiente tarea a una tarea no programada es programada,
            // querra decir que esta por en medio de la lista todavia
            if (!ti.programada() && tj.programada()) {
                return true;
            }
        }
        return false;
    }

    public boolean addNodo(Nodo n) {
        super.addNodo(n);
        changeSupport.firePropertyChange("grafoET.addedNodo", true, false);
        return true;
    }

    public boolean removeNodo(Nodo n) {
        super.removeNodo(n);
        changeSupport.firePropertyChange("grafoET.removedNodo", true, false);
        return true;
    }

    // añade una clase que escuchará las notificaciones de cambio en el estado
    // interno del grafo.
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        changeSupport.addPropertyChangeListener(listener);
    }

    public boolean hayTareasNoProgramadas() {
        for (Nodo n : nodos) {
            Tarea t = (Tarea)n;
            return !t.programada();
        }

        return false;
    }

    public Tarea removeLargestTareaNoProgramada() {
        Tarea largest = new Tarea("", -1);

        for (Nodo n : nodos) {
            Tarea t = (Tarea)n;
            if (!t.programada() && t.duracion() > largest.duracion())
                largest = t;
        }

        removeNodo(largest);

        return largest;
    }
}
